#!/bin/bash
#
# Simple script implementing a temperature dependent fan speed control
# Supported Linux kernel versions: 2.6.5 and later
#
# Version 0.70
#
# Usage: fancontrol.service [CONFIGFILE]
#
# Dependencies:
#   bash, egrep, sed, cut, sleep, readlink, lm_sensors :)
#
# Please send any questions, comments or success stories to
# marius.reiner@hdev.de
# Thanks!
#
# For configuration instructions and warnings please see fancontrol.txt, which
# can be found in the doc/ directory or at the website mentioned above.
#
#
#    Copyright 2003 Marius Reiner <marius.reiner@hdev.de>
#    Copyright (C) 2007-2009 Jean Delvare <khali@linux-fr.org>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#    MA 02110-1301 USA.
#
#

PIDFILE="/var/run/fancontrol.pid"

#DEBUG=1
MAX=255

function LoadConfig
{
	local fcvcount fcv

	echo "Loading configuration from $1 ..."
	if [ ! -r "$1" ]
	then
		echo "Error: Can't read configuration file" >&2
		exit 1
	fi

	# grep configuration from file
	INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'`
	DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'`
	DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'`
	FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'`
	MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'`
	MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'`
	MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'`
	MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'`
	HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g')
	FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g')
	FCMINTEMP=$MINTEMP
	FCMAXTEMP=$MAXTEMP
	FCMINSTART=$MINSTART
	FCMINSTOP=$MINSTOP

	FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'`

	# Check whether all mandatory settings are set
	if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]]
	then
		echo "Some mandatory settings missing, please check your config file!" >&2
		exit 1
	fi
	if [ "$INTERVAL" -le 0 ]
	then
		echo "Error in configuration file:" >&2
		echo "INTERVAL must be at least 1" >&2
		exit 1
	fi

	# write settings to arrays for easier use and print them
	echo "Common settings:"
	
	temp_string=$FCTEMPS
	
	let fcvcount=0
	for fcv in $FCTEMPS
	do
		fcvcount=$((fcvcount+1))
		AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount )
		AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' )
		AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' )

		#if [ $fcvcount -eq 5 ];then
			#echo  "0x00" > '/sys/bus/i2c/devices/6-0058/psu_select_member'
		#	AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} )
		#elif [ $fcvcount -eq 6 ];then
			#echo  "0x20" > '/sys/bus/i2c/devices/6-0058/psu_select_member'
		#	AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} )
		#else
		#	AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} )	
		#fi
		AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} )	
		AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 ))
		echo "AFCTEMP[$fcvcount]=${AFCTEMP[$fcvcount]} (Celsius)"
	done

	fan_string=$FCFANS
	fcvcount=0
	zero=0
	for fcv in $FCFANS
	do
		fcvcount=$((fcvcount+1))
		AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount )
		AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' )
		AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' )
		AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}"  | sed 's/$/_percentage/g')
		AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} )
		if [ "${AFCFAN[$fcvcount]}" == 960 ]
		then
			AFCFAN[$fcvcount]=$zero
		fi
		echo "AFCFAN[$fcvcount]=${AFCFAN[$fcvcount]} (rpm)"
	done
	echo "INTERVAL=$INTERVAL"
	echo "DEVPATH=$FCDEVPATH"
	echo "MINTEMP=$FCMINTEMP"
	echo "MAXTEMP=$FCMAXTEMP"
	echo "MINSTART=$FCMINSTART"
	echo "MINSTOP=$FCMINSTOP"
}

# Check that all referenced sysfs files exist
function CheckFiles
{
	local outdated=0 fcvcount tsen fan
	if [ $outdated -eq 1 ]
	then
		echo >&2
		echo "At least one referenced file is missing. Either some required kernel" >&2
		echo "modules haven't been loaded, or your configuration file is outdated." >&2
		echo "In the latter case, you should run pwmconfig again." >&2
	fi
	return $outdated
}

LoadConfig $1

# Detect path to sensors
if [ ! -d $DIR ]
then
	echo $0: 'No sensors found! (did you load the necessary modules?)' >&2
	exit 1
fi
cd $DIR

# Check for configuration change
if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ]
then
	echo "Configuration is too old, please run pwmconfig again" >&2
	exit 1
fi
if [ "$DIR" = "/" -a -n "$DEVPATH" ]
then
	echo "Unneeded DEVPATH with absolute device paths" >&2
	exit 1
fi
CheckFiles || exit 1

if [ -f "$PIDFILE" ]
then
	echo "File $PIDFILE exists, is fancontrol already running?" >&2
	exit 1
fi
echo $$ > "$PIDFILE"


# main function
function UpdateThermalSensors
{
	echo ""
	TEMP_HIGHEST=0
	FAN_PERCENTAGE=0

	for i in ${AFCTEMP_PATH[@]}; do 
    	if (( $(cat $i) > $TEMP_HIGHEST )); then 
        	TEMP_HIGHEST=$(cat $i); 
    	fi;
	done
	TEMP_HIGHEST=$((TEMP_HIGHEST/1000))
	echo "The highest temperature of thermal sensors: $TEMP_HIGHEST C"

}

function UpdateFanSpeeds
{
	if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50
    	FAN_PERCENTAGE=40
	elif [ $TEMP_HIGHEST -lt 56 -a $TEMP_HIGHEST -gt 50 ]; then #50<TEMP<=55
	    FAN_PERCENTAGE=60
	elif [ $TEMP_HIGHEST -lt 61 -a $TEMP_HIGHEST -gt 55 ]; then #55<TEMP<=60
	    FAN_PERCENTAGE=80
	elif [ $TEMP_HIGHEST -lt 66 -a $TEMP_HIGHEST -gt 60 ]; then #60<TEMP<=65
	    FAN_PERCENTAGE=90
	elif [ $TEMP_HIGHEST -gt 65 ]; then # 65<TEMP
	    FAN_PERCENTAGE=100
	else
	    FAN_PERCENTAGE=100
	fi

	echo "Trying to set fan speed to $FAN_PERCENTAGE %"
	#Set speed to fan1~fan10
	let fcvcount=0
	for fcv in $FCFANS
	do
		fcvcount=$(( fcvcount + 1 ))
		echo  $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]} 
		AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} )

		if [ "${AFCFAN[$fcvcount]}" == 960 ]
		then
			AFCFAN[$fcvcount]=$zero
		fi
		echo "AFCFAN[$fcvcount]=${AFCFAN[$fcvcount]} (rpm)"
	done

	if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50
    	FAN_ON_PSU_PERCENTAGE=50
	elif [ $TEMP_HIGHEST -lt 100 -a $TEMP_HIGHEST -gt 50 ]; then #50<TEMP<100
		FAN_ON_PSU_PERCENTAGE=100
	else
		echo "Unable to get thermal temperature"
		FAN_ON_PSU_PERCENTAGE=100
	fi
	#Set speed to PSU_FAN1
	#echo  "0x00" > '/sys/bus/i2c/devices/4-0058/psu_select_member'
	echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/6-0059/fan1_set_percentage'
	echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/6-0059/fan1_input' ) (rpm)"
	#Set speed to PSU_FAN2
	#echo  "0x20" > '/sys/bus/i2c/devices/6-0058/psu_select_member'
	echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/6-0058/fan1_set_percentage'
	echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/6-0058/fan1_input' ) (rpm)"

	rm -f "$PIDFILE"
}
# main loop calling the main function at specified intervals
while true
do
	UpdateThermalSensors
	UpdateFanSpeeds
	echo "Sleep $INTERVAL seconds ..."
	# Sleep while still handling signals
	sleep $INTERVAL &
	wait $!
done
